package com.lf.freezingpoint.common.util;

import com.alibaba.fastjson2.JSON;
import com.lf.freezingpoint.common.entity.Claims;
import com.lf.freezingpoint.common.entity.R;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;

import java.text.ParseException;
import java.util.Date;
import java.util.UUID;

/**
 * JWT工具类
 */
public class JWTUtil {
    //密钥
    private static final String secret = "trs1xgfe5rsgh9jhjpolm1nb6vcx3zaqwe4rfxc";

    //过期时间7天，单位毫秒
    private static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;

    /**
     * 创建token
     *
     * @param claims 用户信息
     * @return 令牌
     */
    public static String createToken(Claims claims) {
        try {
            //对密钥进行签名
            JWSSigner jwsSigner = new MACSigner(secret);

            //准备JWS header
            JWSHeader jwsHeader = new JWSHeader
                    .Builder(JWSAlgorithm.HS256)
                    .type(JOSEObjectType.JWT)
                    .build();

            //准备JWS payload
            claims.setJti(UUID.randomUUID().toString());
            claims.setIat(new Date().getTime());
            claims.setExp(new Date(System.currentTimeMillis() + EXPIRE).getTime());

            Payload payload = new Payload(JSON.toJSONString(claims));

            //封装JWS对象
            JWSObject jwsObject = new JWSObject(jwsHeader, payload);

            //签名
            jwsObject.sign(jwsSigner);

            return jwsObject.serialize();

        } catch (KeyLengthException e) {
            e.printStackTrace();
        } catch (JOSEException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 验证并获取用户信息
     *
     * @param token 令牌
     * @return 解析后用户信息
     */
    public static R verifyToken(String token) {
        JWSObject jwsObject;
        try {
            jwsObject = JWSObject.parse(token);

            //HMAC验证器
            JWSVerifier jwsVerifier = new MACVerifier(secret);
            if (!jwsObject.verify(jwsVerifier)) {
                return R.fail("token无效");
            }

            String payload = jwsObject.getPayload().toString();
            Claims claims = JSON.parseObject(payload, Claims.class);
            if (claims.getExp() < new Date().getTime()) {
                return R.fail("token已过期");
            }

            return R.ok(claims, "解析成功");
        } catch (ParseException | JOSEException e) {
            e.printStackTrace();
        }
        return R.fail("token无效");

    }

}
